import socket
import struct
import os
import fpm_pb2 as fpm
import time
import logging
import platform
import json
import fcntl, termios, array
import _thread
from multiprocessing import Process, Queue


# logger = logging.getLogger(__name__)
# logger.setLevel(level = logging.INFO)
# handler = logging.FileHandler('/tmp/fpmlog')
# handler.setLevel(logging.INFO)
# formatter = logging.Formatter('%(asctime)s - %(created).6f - %(message)s')
# handler.setFormatter(formatter)
# logger.addHandler(handler)

class FPMServer:
    def __init__(self):
        self.logfile = open('log', 'a')
        self.q = Queue()
        _thread.start_new_thread(self.writeQueue, (0, 0))

        addr = ('0.0.0.0', 2620)
        s = socket.socket()
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(addr)
        s.listen(1000)

        while True:
            c, addr = s.accept()
            _thread.start_new_thread(self.on_new_client, (c, addr))

    def on_new_client(self, conn, addr):
        print('conn from: %s' % conn.getpeername()[0])
        while True:
            data = conn.recv(4)
            d = bytearray(data)
            x, y, size = struct.unpack('>ccH', d)
            body = conn.recv(size - 4)
            m = fpm.Message()
            try:
                m.ParseFromString(body)
            except:
                print(m)
                continue
            # print(m)
            if m.HasField('add_route'):
                # if m.add_route.protocol == fpm.qpb__pb2.OSPF:
                if m.add_route.protocol == fpm.qpb__pb2.BGP:
                    self.logUpdate(m, conn.getpeername()[0])
            if m.HasField('delete_route'):
                self.logUpdate(m, conn.getpeername()[0])

    def writeQueue(self, x, y):
        while True:
            item = self.q.get()
            # print(item)
            if item is None:
                break
            self.logfile.write(item + '\n')
            self.logfile.flush()

    # def writeLog(self, s):
    #     self.logfile.write(s + '\n')

    def logUpdate(self, m, source):
        info = [
            source,
            time.time(),
            m.type
        ]
        
        if m.HasField('add_route'):
            info.append(int.from_bytes(m.add_route.key.prefix.bytes, 'big'))
            info.append(m.add_route.key.prefix.length)
            info.append(m.add_route.nexthops[0].if_id.index)
        elif m.HasField('delete_route'):
            info.append(int.from_bytes(m.delete_route.key.prefix.bytes, 'big'))
            info.append(m.delete_route.key.prefix.length)
        self.q.put(','.join(map(str, info)))


if __name__ == '__main__':
    FPMServer()